package com.xingmei.custom.queue;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ArrayQueue<T> {

    // 用于控制压入、弹出元素
    private final ReentrantLock lock;

    // 保存队列元素
    private final Object[] array;

    // 用于队列无数据等待
    private final Condition empty;

    // 用于队列满了等待
    private final Condition full;

    // 元素准备压入的位置
    private int putIndex;

    // 元素准备弹出的位置
    private int takeIndex;

    // 有效元素的数量
    private int dataCount;

    // 记录压入的总元素
    protected int sumDataCount;

    public ArrayQueue(int capacity) {
        array = new Object[capacity];
        lock = new ReentrantLock();
        empty = lock.newCondition();
        full = lock.newCondition();
    }

    public void put(Object obj) throws InterruptedException {
        lock.lock();
        try {
            if(dataCount == array.length) {
                full.await();
            }
            array[putIndex] = obj;
            dataCount++;
            putIndex++;
            sumDataCount++;
            if(putIndex == array.length) {
                putIndex = 0;
            }
            empty.signal();
        } finally {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            if (dataCount==0) {
                takeIndex = 0;
                empty.await();
            }
            Object obj = array[takeIndex];
            dataCount--;
            takeIndex++;
            if (takeIndex == array.length) {
                takeIndex = 0;
            }
            full.signal();
            return obj;
        }finally {
            lock.unlock();
        }
    }
}
